Fix SMP TLB flushing in XenLinux 2.6.
Signed-off-by: Keir Fraser <keir@xensource.com>
#include <linux/pci.h>
#include <linux/version.h>
#include <asm/io.h>
+#include <asm/tlbflush.h>
#include <asm-xen/balloon.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
phys_to_machine_mapping[(__pa(vstart)>>PAGE_SHIFT)+i] =
pfn+i;
}
- xen_tlb_flush();
+ flush_tlb_all();
- balloon_unlock(flags);
+ balloon_unlock(flags);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
#include <mach_ipi.h> /* must come after the send_IPI functions above for inlining */
+#if 0 /* XEN */
/*
* Smarter SMP flushing macros.
* c/o Linus Torvalds.
on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
}
+#else
+
+irqreturn_t smp_invalidate_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{ return 0; }
+void flush_tlb_current_task(void)
+{ xen_tlb_flush_mask(current->mm->cpu_vm_mask); }
+void flush_tlb_mm(struct mm_struct * mm)
+{ xen_tlb_flush_mask(mm->cpu_vm_mask); }
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
+{ xen_invlpg_mask(vma->vm_mm->cpu_vm_mask, va); }
+void flush_tlb_all(void)
+{ xen_tlb_flush_all(); }
+
+#endif /* XEN */
+
/*
* this function sends a 'reschedule' IPI to another CPU.
* it goes straight through and wastes no time serializing
#include <linux/vmalloc.h>
#include <asm/page.h>
#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
#include <asm-xen/hypervisor.h>
#include <asm-xen/balloon.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
}
+#ifdef CONFIG_SMP
+
+void xen_tlb_flush_all(void)
+{
+ struct mmuext_op op;
+ op.cmd = MMUEXT_TLB_FLUSH_ALL;
+ BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+}
+
+void xen_tlb_flush_mask(cpumask_t mask)
+{
+ struct mmuext_op op;
+ op.cmd = MMUEXT_TLB_FLUSH_MULTI;
+ op.cpuset = mask.bits[0];
+ BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+}
+
+void xen_invlpg_all(unsigned long ptr)
+{
+ struct mmuext_op op;
+ op.cmd = MMUEXT_INVLPG_ALL;
+ op.linear_addr = ptr & PAGE_MASK;
+ BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+}
+
+void xen_invlpg_mask(cpumask_t mask, unsigned long ptr)
+{
+ struct mmuext_op op;
+ op.cmd = MMUEXT_INVLPG_MULTI;
+ op.cpuset = mask.bits[0];
+ op.linear_addr = ptr & PAGE_MASK;
+ BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+}
+
+#endif /* CONFIG_SMP */
+
void xen_pgd_pin(unsigned long ptr)
{
struct mmuext_op op;
phys_to_machine_mapping[__pa(vstart)>>PAGE_SHIFT] = INVALID_P2M_ENTRY;
}
- xen_tlb_flush();
+ flush_tlb_all();
balloon_put_pages(pfn_array, 1 << order);
/* Ensure that ballooned highmem pages don't have cached mappings. */
kmap_flush_unused();
-
- xen_tlb_flush();
+ flush_tlb_all();
/* No more mappings: invalidate pages in P2M and add to balloon. */
for ( i = 0; i < debt; i++ )
do { \
if (__dirty) { \
if ( likely((__vma)->vm_mm == current->mm) ) { \
- HYPERVISOR_update_va_mapping((__address), (__entry), UVMF_INVLPG_LOCAL); \
+ HYPERVISOR_update_va_mapping((__address), (__entry), 0); \
+ flush_tlb_page((__vma), (__address)); \
} else { \
xen_l1_entry_update((__ptep), (__entry).pte_low); \
flush_tlb_page((__vma), (__address)); \
#include <asm/processor.h>
#define __flush_tlb() xen_tlb_flush()
-
-/*
- * Global pages have to be flushed a bit differently. Not a real
- * performance problem because this does not happen often.
- */
#define __flush_tlb_global() xen_tlb_flush()
+#define __flush_tlb_all() xen_tlb_flush()
extern unsigned long pgkern_mask;
-# define __flush_tlb_all() \
- do { \
- if (cpu_has_pge) \
- __flush_tlb_global(); \
- else \
- __flush_tlb(); \
- } while (0)
-
#define cpu_has_invlpg (boot_cpu_data.x86 > 3)
#define __flush_tlb_single(addr) xen_invlpg(addr)
void xen_set_ldt(unsigned long ptr, unsigned long bytes);
void xen_machphys_update(unsigned long mfn, unsigned long pfn);
+#ifdef CONFIG_SMP
+#include <linux/cpumask.h>
+void xen_tlb_flush_all(void);
+void xen_invlpg_all(unsigned long ptr);
+void xen_tlb_flush_mask(cpumask_t mask);
+void xen_invlpg_mask(cpumask_t mask, unsigned long ptr);
+#endif
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
/*
** XXX SMH: 2.4 doesn't have percpu.h (or support SMP guests) so just